package hyperNexusCommon

import (
	"fmt"
	"reflect"
	"time"
)

// Convert 将普通结构体转换为 Protobuf 生成的结构体，处理 time.Time 到字符串的转换
func ConvertToProtocol(src, dst interface{}) error {
	// 检查 src 是否为指向结构体的指针
	srcVal := reflect.ValueOf(src)
	if srcVal.Kind() != reflect.Ptr || srcVal.Elem().Kind() != reflect.Struct {
		return fmt.Errorf("src 必须是指向结构体的指针")
	}
	srcVal = srcVal.Elem()

	// 检查 dst 是否为指向结构体的指针
	dstVal := reflect.ValueOf(dst)
	if dstVal.Kind() != reflect.Ptr || dstVal.Elem().Kind() != reflect.Struct {
		return fmt.Errorf("dst 必须是指向结构体的指针")
	}
	dstVal = dstVal.Elem()

	// 遍历源结构体的所有字段
	for i := 0; i < srcVal.NumField(); i++ {
		srcField := srcVal.Field(i)
		srcTypeField := srcVal.Type().Field(i)
		dstField := dstVal.FieldByName(srcTypeField.Name)

		// 跳过目标结构体不存在的字段
		if !dstField.IsValid() {
			continue
		}

		// 检查目标字段是否可设置
		if !dstField.CanSet() {
			return fmt.Errorf("目标字段 %s 不可设置", srcTypeField.Name)
		}

		// 处理 time.Time 类型转换
		if srcField.Type() == reflect.TypeOf(time.Time{}) {
			if dstField.Kind() != reflect.String {
				return fmt.Errorf("目标字段 %s 应为字符串类型", srcTypeField.Name)
			}
			timeVal := srcField.Interface().(time.Time)
			formattedTime := timeVal.Format("2006-01-02 15:04:05")
			dstField.SetString(formattedTime)
		} else {
			// 检查类型是否匹配
			if srcField.Type() != dstField.Type() {
				return fmt.Errorf("字段 %s 类型不匹配: 原类型 %s, 目标类型 %s",
					srcTypeField.Name, srcField.Type(), dstField.Type())
			}
			// 直接赋值相同类型的字段
			dstField.Set(srcField)
		}
	}

	return nil
}
